#include <cstring>
#include <iostream>

using namespace std;

class A {
 public:
  A() = default;

  // 1. 隐含 Print(A *const this)
  // void Print() { cout << "Hello World" << endl; }
  // 2. 隐含 Print(const A *const this)
  void Print() const { cout << "Hello World" << endl; }

  // 隐含 (A *const this, const A &a)
  bool operator>(const A &a) {
    return true;  // TEST
  }
};

void callPrint(const A *a) {
  // 隐含 a->Print(const A *a);
  a->Print();  // 若使用1版本则报错
}

int main(int argc, char const *argv[]) {
  // PART 1
  A *a = new A;
  a->Print();
  callPrint(a);

  // PART 2
  A b;
  const A c;
  // 隐含 b.operator>(A *b, const A &c);
  b > c;
  // 隐含 c.operator>(const A *c, const A &b);
  // c > b; // FAILED

  /**
   * 总结：
   * 1. const对象只可调用const成员函数，不可调用非const成员函数
   * 2. 非const对象可调用任何成员函数
   * 3. const成员函数内只能调用const成员函数与const成员变量
   * 4. 非const成员函数内可调用任何成员函数与成员变量
  */

  // PART 3
  char *str = new char[5]{0};
  strcpy(str, "hello");

  // 指针常量：指向常量的指针
  const char *p = str;
  // p[0] = 'H'; // FAILED
  p = "World";  // ALLOW

  // 常量指针：指此指针的值不可变
  char *const cp = str;
  // cp = "Hello"; // FAILED
  cp[0] = 'H';  // ALLOW

  cout << p << endl;
  cout << cp << endl;

  delete[] str;
  return 0;
}
